"""
Author : ZhengShiQi
DateTime: 2025/9/11 14:00
FileName: mock_service.py
description: 同步配置WireMock
"""
import logging
import requests
import uuid
from app.config import settings  # 假设配置了WireMock的地址
from app.services.db_service import create_mock_api, get_mock_api_by_id, update_mock_api, delete_mock_api, \
    get_all_mock_apis
from app.models.schemas import MockApiCreate, HttpMethod
from app.models.database import MockApiConfig
from sqlalchemy.orm import Session
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class WireMockService:
    def __init__(self):
        self.base_url = settings.WIREMOCK_URL

    def create_mapping(self, mock_api: MockApiCreate):
        """在WireMock中创建映射规则"""
        logger.info(f"这是映射body{mock_api}")
        mapping = {
            "request": {
                "method": mock_api.method if hasattr(mock_api, 'method') else HttpMethod.GET,  # 使用mock_api中的方法属性，默认为GET
                "url": mock_api.url
            },
            "response": {
                "status": mock_api.status_code,
                "headers": mock_api.headers,
                "jsonBody": mock_api.body
            }
        }
        response = requests.post(f"{self.base_url}/__admin/mappings", json=mapping)
        response.raise_for_status()  # 处理错误
        return response.json()
    
    def delete_mapping(self, mapping_id: str):
        """在WireMock中删除映射规则"""
        response = requests.delete(f"{self.base_url}/__admin/mappings/{mapping_id}")
        response.raise_for_status()
        return response.status_code == 200
    
    def update_mapping(self, mapping_id: str, method: str, mock_api: MockApiCreate):
        """在WireMock中更新映射规则"""
        # 直接使用传入的ID
        mapping = {
            "request": {
                "method": method,  # 使用传入的方法参数
                "url": mock_api.url
            },
            "response": {
                "status": mock_api.status_code,
                "headers": mock_api.headers,
                "jsonBody": mock_api.body
            }
        }
        logger.info(f"这是wiremock映射的body对象{type(mock_api.body)},{mock_api}")
        response = requests.put(f"{self.base_url}/__admin/mappings/{mapping_id}", json=mapping)
        logger.info(f"这是wiremock映射的body对象{response}")
        response.raise_for_status()
        return response.json()

    def get_mapping(self, mapping_id: str):
        """获取WireMock中的映射规则"""
        try:
            response = requests.get(f"{self.base_url}/__admin/mappings/{mapping_id}")
            response.raise_for_status()
            return response.json()
        except requests.exceptions.HTTPError as e:
            if response.status_code == 404:
                return None
            else:
                raise e

def create_mock_api_with_wiremock(db: Session, mock_api: MockApiCreate):
    """创建Mock API并同步到WireMock"""
    try:
        # 先同步到WireMock
        wiremock_service = WireMockService()
        wiremock_response = wiremock_service.create_mapping(mock_api)
        logger.info(f"这是返回的映射{wiremock_response},这是body{mock_api.body}，这是转换之后的{str(mock_api.body)}")
        # 创建数据库记录（存储wiremock_id）
        return create_mock_api(db, mock_api, wiremock_id=wiremock_response.get('id'))
    except Exception as e:
        raise Exception(f"无法连接到WireMock服务: {str(e)}")

def get_mock_configs(db: Session):
    """获取所有Mock配置"""
    return get_all_mock_apis(db)

def create_mock_config(db: Session, mock_api: MockApiCreate):
    """创建Mock配置并同步到WireMock"""
    try:
        # 先同步到WireMock
        wiremock_service = WireMockService()
        wiremock_response = wiremock_service.create_mapping(mock_api)
        
        # 使用WireMock返回的ID作为wiremock_id存储
        mock_api_dict = mock_api.dict()
        mock_api_dict['wiremock_id'] = wiremock_response.get('id')
        # 确保method字段被正确传递
        mock_api_dict['method'] = mock_api_dict.get('method', 'GET')
        
        # 创建数据库记录
        # 直接使用字典创建MockApiConfig对象，而不是通过MockApiCreate
        from app.models.database import MockApiConfig
        db_mock = MockApiConfig(**mock_api_dict)
        db.add(db_mock)
        db.commit()
        db.refresh(db_mock)
        return db_mock
    except Exception as e:
        raise Exception(f"无法连接到WireMock服务: {str(e)}")

def update_mock_config(db: Session, id: int, mock_api: MockApiCreate):
    """更新Mock配置并同步到WireMock"""
    try:
        # 先从数据库获取配置
        db_mock_api = get_mock_api_by_id(db, id)
        if not db_mock_api:
            raise Exception("数据库中未找到对应的Mock配置")
        
        # 使用数据库记录的wiremock_id作为WireMock的ID
        wiremock_id = db_mock_api.wiremock_id
        wiremock_service = WireMockService()
        
        # 检查WireMock中是否存在该映射
        if wiremock_id:
            mapping = wiremock_service.get_mapping(wiremock_id)
            if not mapping:
                # 如果不存在，则创建新的映射
                wiremock_response = wiremock_service.create_mapping(mock_api)
                # 更新数据库记录的wiremock_id
                db_mock_api.wiremock_id = wiremock_response.get('id')
                db.commit()
                db.refresh(db_mock_api)
                wiremock_id = db_mock_api.wiremock_id
        else:
            # 如果wiremock_id为空，则创建新的映射
            wiremock_response = wiremock_service.create_mapping(mock_api)
            # 更新数据库记录的wiremock_id
            db_mock_api.wiremock_id = wiremock_response.get('id')
            db.commit()
            db.refresh(db_mock_api)
            wiremock_id = db_mock_api.wiremock_id
        
        # 同步到WireMock
        wiremock_service.update_mapping(wiremock_id, db_mock_api.method, mock_api)
        
        # 更新数据库记录
        # 确保method字段被正确传递
        mock_api_dict = mock_api.dict()
        if 'method' not in mock_api_dict or mock_api_dict['method'] is None:
            mock_api_dict['method'] = 'GET'
        mock_api_with_method = MockApiCreate(**mock_api_dict)
        return update_mock_api(db, id, mock_api_with_method)
    except Exception as e:
        raise Exception(f"无法连接到WireMock服务: {str(e)}")

def delete_mock_config(db: Session, mock_id: int):
    """删除Mock配置并同步到WireMock"""
    try:
        # 先从数据库获取配置
        db_mock_api = get_mock_api_by_id(db, mock_id)
        if not db_mock_api:
            raise Exception("Mock配置不存在")
        
        # 删除WireMock中的配置
        wiremock_service = WireMockService()
        wiremock_service.delete_mapping(db_mock_api.wiremock_id)
        
        # 删除数据库中的配置
        return delete_mock_api(db, mock_id)
    except Exception as e:
        raise Exception(f"无法连接到WireMock服务: {str(e)}")